using System;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Xml;
using System.Reflection;
using Coffee.DataMappers;

namespace Coffee.SurveyControls
{
    /// <summary>
    /// Summary description for ISurveyControl
    /// </summary>
    public abstract class SurveyControl : UserControl
    {
        protected int ctlCounter = 0;

        public ControlList SurveyControls;
        protected IDataMapper _mapper = null;
        protected DataSet dsQuestions = null;

        public IDataMapper Mapper
        {
            get { return _mapper; }
        }

        public DataSet Questions
        {
            get { return dsQuestions; }
            set { dsQuestions = value; }
        }


        //public Page page = null;
        protected XmlNode configuration = null;
        protected SurveyManager pSurveyManager;
        protected bool locked;
        private string pageId;

        public bool IsDirty { get { return CheckIsDirty(); } }

        protected virtual bool CheckIsDirty()
        {
            return true;
        }

        public bool Locked { get { return locked; } set { locked = value; } }

        public SurveyControl()
        {
            SurveyControls = new ControlList();
        }



        public SurveyControl(SurveyManager manager, XmlNode configuration)
        {
            SurveyControls = new ControlList();
            this.pSurveyManager = manager;
            //this.page = Coffee.Page;
            this.configuration = configuration;

            _mapper = DataMapperFactory.CreateMapper(configuration);

        }

        public virtual void Initialize()
        {
        }

        public virtual void LoadData()
        {
        }

        public virtual void LoadDynamicControls()
        {
        }

        public virtual void SaveData()
        {
        }

        public virtual bool Validate()
        {
            return true;
        }

        public virtual void WireEvents(bool isCallBack)
        {
        }


        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        }

        protected override void CreateChildControls()
        {
            Initialize();
            if (!this.Page.IsPostBack || reloadData)
                LoadData();
            //LoadDynamicControls();
            WireEvents(true);
            base.CreateChildControls();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            WireEvents(false);
            base.RenderControl(writer);
        }

        bool reloadData;

        public bool ReloadData { get { return reloadData; } set { reloadData = value; } }

        // implement some sort of hooking mechanism that will allow developers to run additional code
        // upon load/save/validate/initialize

        /// <summary>
        /// Helper function that calls LoadControl with parameters
        /// </summary>
        /// <param name="page"></param>
        /// <param name="path"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static SurveyControl LoadControl(string path, object[] parameters)
        {
            SurveyControl uc = (SurveyControl)((Page)HttpContext.Current.Handler).LoadControl(path);
            Type[] paramTypes = new Type[parameters.Length];
            for (int paramLoop = 0; paramLoop < parameters.Length; paramLoop++)
                paramTypes[paramLoop] = parameters[paramLoop].GetType();

            ConstructorInfo constructor = uc.GetType().BaseType.GetConstructor(paramTypes);
            constructor.Invoke(uc, parameters);

            return uc;
        }

        public static Control LoadBasicControl(string path, object[] parameters)
        {
            Control uc = ((Page)HttpContext.Current.Handler).LoadControl(path);
            Type[] paramTypes = new Type[parameters.Length];
            for (int paramLoop = 0; paramLoop < parameters.Length; paramLoop++)
                paramTypes[paramLoop] = parameters[paramLoop].GetType();

            ConstructorInfo constructor = uc.GetType().BaseType.GetConstructor(paramTypes);
            constructor.Invoke(uc, parameters);

            return uc;
        }

        /// <summary>
        /// Need to standardize FindControl behavior
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual new object FindControl(string id)
        {
            if (SurveyControls.ContainsKey(id))
            {
                return SurveyControls[id];
            }
            foreach (Control ctl in SurveyControls.Values)
            {
                if (ctl.GetType().BaseType == typeof(SurveyControl))
                {
                    object ctlFound = ((SurveyControl)ctl).FindControl(id);
                    if (ctlFound != null) return ctlFound;
                }
            }
            return null;
        }

    }
}